package com.boco.common.util;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.FatalBeanException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Properties;

/**
 * @author pandengke/pdkkpdk@163.com
 * @date 2018/9/25
 */
public class Utils {

    /**
     * 把对象的属性设置到另一个对象,属性不一致的,可以传入映射关系convertProperties
     */
    public static void copyProperties(Object source, Object target, Properties convertProperties) {
        if (convertProperties == null) {
            BeanUtils.copyProperties(source, target);
            return;
        }
        Assert.notNull(source, "Source must not be null");
        Assert.notNull(target, "Target must not be null");
        Class<?> actualEditable = target.getClass();
        PropertyDescriptor[] targetPds = BeanUtils.getPropertyDescriptors(actualEditable);
        for (PropertyDescriptor targetPd : targetPds) {
            Method writeMethod = targetPd.getWriteMethod();
            if (writeMethod != null) {
                String sourceProperties = convertProperties.getProperty(targetPd.getName());
                if (sourceProperties == null) {
                    sourceProperties = targetPd.getName();
                }
                PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(source.getClass(), sourceProperties);
                /*属性映射中*/
                if (sourcePd != null) {
                    Method readMethod = sourcePd.getReadMethod();
                    if (readMethod != null &&
                            ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
                        try {
                            if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
                                readMethod.setAccessible(true);
                            }
                            Object value = readMethod.invoke(source);
                            if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
                                writeMethod.setAccessible(true);
                            }
                            writeMethod.invoke(target, value);
                        } catch (Throwable ex) {
                            throw new FatalBeanException(
                                    "Could not copy property '" + targetPd.getName() + "' from source to target", ex);
                        }
                    }
                }
            }
        }
    }


    public static Collection<String> netaddress() {
        Collection<String> list = new ArrayList<>(10);
        list.add("localhost");
        try {
            Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = allNetInterfaces.nextElement();
                Enumeration addresses = netInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress ip = (InetAddress) addresses.nextElement();
                    if (ip instanceof Inet4Address) {
                        String address = ip.getHostAddress();
                        list.add(address);
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return list;
    }


    public static void runSilently(Runnable runnable) {
        try {
            runnable.run();
        } catch (Throwable e) {
//            ignored
        }
    }

}
